package com.lifeverse.service;

import com.lifeverse.entity.DigitalDNA;
import com.lifeverse.util.JsonUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 基因表达引擎
 * 实现简化版的基因表达算法
 */
@Slf4j
@Component
public class GeneExpressionEngine {
    
    // 环境因子权重
    private static final Map<String, Double> ENVIRONMENT_WEIGHTS = Map.of(
            "stress", 0.8,      // 压力环境
            "cooperation", 0.9,  // 协作环境
            "competition", 0.7,  // 竞争环境
            "learning", 0.85,    // 学习环境
            "creativity", 0.75,  // 创造环境
            "stability", 0.6,    // 稳定环境
            "change", 0.9,       // 变化环境
            "social", 0.8        // 社交环境
    );
    
    // 基因激活阈值
    private static final BigDecimal ACTIVATION_THRESHOLD = BigDecimal.valueOf(30.0);
    
    // 基因间相互作用矩阵
    private static final Map<String, Map<String, Double>> GENE_INTERACTIONS = Map.of(
            "learning", Map.of("logic", 0.8, "adaptability", 0.7, "creativity", 0.6),
            "creativity", Map.of("intuition", 0.9, "emotion", 0.6, "learning", 0.5),
            "collaboration", Map.of("social", 0.9, "emotion", 0.7, "adaptability", 0.6),
            "adaptability", Map.of("learning", 0.8, "collaboration", 0.6, "intuition", 0.5),
            "emotion", Map.of("social", 0.8, "intuition", 0.7, "creativity", 0.6),
            "logic", Map.of("learning", 0.9, "adaptability", 0.5, "creativity", -0.2),
            "intuition", Map.of("creativity", 0.8, "emotion", 0.7, "logic", -0.3),
            "social", Map.of("collaboration", 0.9, "emotion", 0.8, "adaptability", 0.6)
    );
    
    /**
     * 表达DNA基因
     * 根据环境条件激活相应的基因并计算表达强度
     */
    public Map<String, Object> expressGenes(DigitalDNA dna, Map<String, Object> environment) {
        log.debug("Expressing genes for DNA: {}", dna.getId());
        
        Map<String, Object> expressionResult = new HashMap<>();
        
        // 获取基因强度映射
        Map<String, BigDecimal> geneStrengths = extractGeneStrengths(dna);
        
        // 分析环境因子
        Map<String, Double> environmentFactors = analyzeEnvironment(environment);
        
        // 计算每个基因的表达水平
        for (Map.Entry<String, BigDecimal> entry : geneStrengths.entrySet()) {
            String geneName = entry.getKey();
            BigDecimal baseStrength = entry.getValue();
            
            // 计算环境影响
            double environmentImpact = calculateEnvironmentImpact(geneName, environmentFactors);
            
            // 计算基因间相互作用
            double geneInteraction = calculateGeneInteraction(geneName, geneStrengths);
            
            // 计算最终表达水平
            double expressionLevel = calculateExpressionLevel(baseStrength, environmentImpact, geneInteraction);
            
            expressionResult.put(geneName, expressionLevel);
            expressionResult.put(geneName + "_activated", expressionLevel > ACTIVATION_THRESHOLD.doubleValue());
        }
        
        // 计算整体表达指标
        expressionResult.put("overall_activity", calculateOverallActivity(expressionResult));
        expressionResult.put("expression_balance", calculateExpressionBalance(expressionResult));
        expressionResult.put("dominant_genes", identifyDominantGenes(expressionResult));
        
        log.debug("Gene expression completed for DNA: {}, overall activity: {}", 
                dna.getId(), expressionResult.get("overall_activity"));
        
        return expressionResult;
    }
    
    /**
     * 预测基因表达结果
     * 在不实际执行表达的情况下预测结果
     */
    public Map<String, Object> predictExpression(DigitalDNA dna, Map<String, Object> environment) {
        log.debug("Predicting gene expression for DNA: {}", dna.getId());
        
        // 使用相同的算法但不更新DNA状态
        return expressGenes(dna, environment);
    }
    
    /**
     * 计算基因表达适应度
     * 评估基因表达对特定环境的适应程度
     */
    public BigDecimal calculateExpressionFitness(DigitalDNA dna, Map<String, Object> environment) {
        Map<String, Object> expression = expressGenes(dna, environment);
        
        double totalFitness = 0.0;
        int geneCount = 0;
        
        // 计算每个基因的适应度贡献
        for (Map.Entry<String, Object> entry : expression.entrySet()) {
            String key = entry.getKey();
            if (!key.endsWith("_activated") && !key.equals("overall_activity") && 
                !key.equals("expression_balance") && !key.equals("dominant_genes")) {
                
                double expressionLevel = (Double) entry.getValue();
                double environmentDemand = getEnvironmentDemand(key, environment);
                
                // 计算适应度：表达水平与环境需求的匹配程度
                double fitness = 1.0 - Math.abs(expressionLevel - environmentDemand) / 100.0;
                totalFitness += Math.max(0, fitness);
                geneCount++;
            }
        }
        
        BigDecimal averageFitness = BigDecimal.valueOf(totalFitness / geneCount * 100);
        return averageFitness.setScale(2, RoundingMode.HALF_UP);
    }
    
    /**
     * 优化基因表达
     * 根据环境反馈调整基因表达参数
     */
    public Map<String, BigDecimal> optimizeExpression(DigitalDNA dna, Map<String, Object> environment, 
                                                     Map<String, Double> feedback) {
        log.debug("Optimizing gene expression for DNA: {}", dna.getId());
        
        Map<String, BigDecimal> optimizedStrengths = new HashMap<>();
        Map<String, BigDecimal> currentStrengths = extractGeneStrengths(dna);
        
        for (Map.Entry<String, BigDecimal> entry : currentStrengths.entrySet()) {
            String geneName = entry.getKey();
            BigDecimal currentStrength = entry.getValue();
            
            // 获取反馈分数
            Double feedbackScore = feedback.getOrDefault(geneName, 0.5);
            
            // 计算调整幅度
            double adjustmentFactor = (feedbackScore - 0.5) * 0.1; // 最大调整10%
            BigDecimal adjustment = currentStrength.multiply(BigDecimal.valueOf(adjustmentFactor));
            
            // 应用调整
            BigDecimal optimizedStrength = currentStrength.add(adjustment);
            
            // 确保在有效范围内
            optimizedStrength = optimizedStrength.max(BigDecimal.ZERO).min(BigDecimal.valueOf(100));
            
            optimizedStrengths.put(geneName, optimizedStrength);
        }
        
        return optimizedStrengths;
    }
    
    /**
     * 提取DNA的基因强度映射
     */
    private Map<String, BigDecimal> extractGeneStrengths(DigitalDNA dna) {
        return Map.of(
                "learning", dna.getLearningGeneStrength(),
                "creativity", dna.getCreativityGeneStrength(),
                "collaboration", dna.getCollaborationGeneStrength(),
                "adaptability", dna.getAdaptabilityGeneStrength(),
                "emotion", dna.getEmotionGeneStrength(),
                "logic", dna.getLogicGeneStrength(),
                "intuition", dna.getIntuitionGeneStrength(),
                "social", dna.getSocialGeneStrength()
        );
    }
    
    /**
     * 分析环境因子
     */
    private Map<String, Double> analyzeEnvironment(Map<String, Object> environment) {
        Map<String, Double> factors = new HashMap<>();
        
        for (Map.Entry<String, Object> entry : environment.entrySet()) {
            String key = entry.getKey();
            Object value = entry.getValue();
            
            if (value instanceof Number) {
                factors.put(key, ((Number) value).doubleValue());
            } else if (value instanceof Boolean) {
                factors.put(key, (Boolean) value ? 1.0 : 0.0);
            } else if (value instanceof String) {
                // 简单的字符串到数值映射
                factors.put(key, parseStringToDouble((String) value));
            }
        }
        
        return factors;
    }
    
    /**
     * 计算环境对基因的影响
     */
    private double calculateEnvironmentImpact(String geneName, Map<String, Double> environmentFactors) {
        double totalImpact = 1.0; // 基础影响系数
        
        for (Map.Entry<String, Double> factor : environmentFactors.entrySet()) {
            String factorName = factor.getKey();
            Double factorValue = factor.getValue();
            
            // 获取环境权重
            Double weight = ENVIRONMENT_WEIGHTS.getOrDefault(factorName, 0.5);
            
            // 计算特定基因对特定环境因子的敏感度
            double sensitivity = getGeneSensitivity(geneName, factorName);
            
            // 累积环境影响
            totalImpact += (factorValue * weight * sensitivity - 0.5) * 0.2; // 最大20%的影响
        }
        
        return Math.max(0.1, Math.min(2.0, totalImpact)); // 限制在0.1-2.0范围内
    }
    
    /**
     * 计算基因间相互作用
     */
    private double calculateGeneInteraction(String targetGene, Map<String, BigDecimal> allGeneStrengths) {
        double interactionEffect = 0.0;
        
        Map<String, Double> interactions = GENE_INTERACTIONS.getOrDefault(targetGene, Map.of());
        
        for (Map.Entry<String, Double> interaction : interactions.entrySet()) {
            String interactingGene = interaction.getKey();
            Double interactionStrength = interaction.getValue();
            
            BigDecimal geneStrength = allGeneStrengths.getOrDefault(interactingGene, BigDecimal.ZERO);
            
            // 计算相互作用效应
            double effect = (geneStrength.doubleValue() / 100.0) * interactionStrength * 0.1; // 最大10%影响
            interactionEffect += effect;
        }
        
        return 1.0 + interactionEffect; // 基础系数1.0加上相互作用效应
    }
    
    /**
     * 计算最终表达水平
     */
    private double calculateExpressionLevel(BigDecimal baseStrength, double environmentImpact, double geneInteraction) {
        double expressionLevel = baseStrength.doubleValue() * environmentImpact * geneInteraction;
        
        // 应用sigmoid函数进行平滑处理
        expressionLevel = 100.0 / (1.0 + Math.exp(-(expressionLevel - 50.0) / 10.0));
        
        return Math.max(0.0, Math.min(100.0, expressionLevel));
    }
    
    /**
     * 计算整体活跃度
     */
    private double calculateOverallActivity(Map<String, Object> expressionResult) {
        double totalActivity = 0.0;
        int geneCount = 0;
        
        for (Map.Entry<String, Object> entry : expressionResult.entrySet()) {
            String key = entry.getKey();
            if (!key.endsWith("_activated") && !key.equals("overall_activity") && 
                !key.equals("expression_balance") && !key.equals("dominant_genes")) {
                
                totalActivity += (Double) entry.getValue();
                geneCount++;
            }
        }
        
        return geneCount > 0 ? totalActivity / geneCount : 0.0;
    }
    
    /**
     * 计算表达平衡度
     */
    private double calculateExpressionBalance(Map<String, Object> expressionResult) {
        List<Double> expressionLevels = expressionResult.entrySet().stream()
                .filter(entry -> !entry.getKey().endsWith("_activated") && 
                               !entry.getKey().equals("overall_activity") && 
                               !entry.getKey().equals("expression_balance") && 
                               !entry.getKey().equals("dominant_genes"))
                .map(entry -> (Double) entry.getValue())
                .toList();
        
        if (expressionLevels.isEmpty()) {
            return 0.0;
        }
        
        double mean = expressionLevels.stream().mapToDouble(Double::doubleValue).average().orElse(0.0);
        double variance = expressionLevels.stream()
                .mapToDouble(level -> Math.pow(level - mean, 2))
                .average().orElse(0.0);
        
        // 平衡度 = 1 - (标准差 / 最大可能标准差)
        double standardDeviation = Math.sqrt(variance);
        double maxPossibleStdDev = 50.0; // 理论最大标准差
        
        return Math.max(0.0, 1.0 - (standardDeviation / maxPossibleStdDev));
    }
    
    /**
     * 识别主导基因
     */
    private List<String> identifyDominantGenes(Map<String, Object> expressionResult) {
        return expressionResult.entrySet().stream()
                .filter(entry -> !entry.getKey().endsWith("_activated") && 
                               !entry.getKey().equals("overall_activity") && 
                               !entry.getKey().equals("expression_balance") && 
                               !entry.getKey().equals("dominant_genes"))
                .filter(entry -> (Double) entry.getValue() > 70.0) // 表达水平超过70%
                .map(Map.Entry::getKey)
                .sorted()
                .toList();
    }
    
    /**
     * 获取基因对环境因子的敏感度
     */
    private double getGeneSensitivity(String geneName, String environmentFactor) {
        // 基因-环境敏感度矩阵
        Map<String, Map<String, Double>> sensitivities = Map.of(
                "learning", Map.of("learning", 1.0, "stress", 0.7, "stability", 0.8),
                "creativity", Map.of("creativity", 1.0, "change", 0.9, "stress", 0.6),
                "collaboration", Map.of("cooperation", 1.0, "social", 0.9, "competition", 0.3),
                "adaptability", Map.of("change", 1.0, "stress", 0.8, "stability", 0.2),
                "emotion", Map.of("social", 0.9, "stress", 0.8, "cooperation", 0.7),
                "logic", Map.of("stability", 0.9, "learning", 0.8, "creativity", 0.3),
                "intuition", Map.of("creativity", 0.8, "change", 0.7, "logic", 0.2),
                "social", Map.of("social", 1.0, "cooperation", 0.9, "collaboration", 0.8)
        );
        
        return sensitivities.getOrDefault(geneName, Map.of())
                .getOrDefault(environmentFactor, 0.5);
    }
    
    /**
     * 获取环境对基因的需求程度
     */
    private double getEnvironmentDemand(String geneName, Map<String, Object> environment) {
        // 根据环境条件计算对特定基因的需求程度
        double demand = 50.0; // 基础需求
        
        for (Map.Entry<String, Object> entry : environment.entrySet()) {
            String envKey = entry.getKey();
            Object envValue = entry.getValue();
            
            if (envValue instanceof Number) {
                double value = ((Number) envValue).doubleValue();
                double sensitivity = getGeneSensitivity(geneName, envKey);
                demand += (value - 50.0) * sensitivity * 0.5; // 调整需求
            }
        }
        
        return Math.max(0.0, Math.min(100.0, demand));
    }
    
    /**
     * 解析字符串为数值
     */
    private double parseStringToDouble(String value) {
        return switch (value.toLowerCase()) {
            case "high", "strong", "active" -> 80.0;
            case "medium", "moderate", "normal" -> 50.0;
            case "low", "weak", "inactive" -> 20.0;
            case "very_high", "maximum" -> 95.0;
            case "very_low", "minimum" -> 5.0;
            default -> 50.0;
        };
    }
}